<script>
    /*
        一、主模块数据库上下文 与 模块数据库上下文 的关系？

            在ABP框架中，主解决方案数据库上下文与 "模块数据库上下文关系如下"

                    1、主DbContext强制替换模块DbContext

                                需要主DbContext 实现模块的DbContext接口,并在主DbContext内注册模块DbContext的DbSet属性。

                    2、模块DbContext 独立于主DbContext

                                不需要主DbContext 实现模块的DbContext接口, 主DbContext 不需要注册模块DbContext的DbSet属性。

            



    */
    /*
        二、那如果不做任何设置，不强制替换内置模块，但是内置模块的表会在同一个库里吗？

                        如果不做任何额外设置(不替换内置模块DbContext、不修改链接字符串)，ABP内置模块的表会默认和你的业务表创建在同一个数据库中，

                        ------这是ABP的默认行为，核心原因是 [所有模块默认使用主项目的Default连接字符串]

                        下面用通俗的逻辑+ 验证步骤，帮你彻底搞懂：


                    1、核心原理：

                              模块如何 "自动复用" 主数据库？

                              ABP框架的模块遵循 [链接字符串优先级规则]，默认情况下：

                                        <1>、所有内置模块 (Identity、TenantManagement、Permission等)都会优先使用名为 "Default"的连接字符串。

                                        <2>、你的项目 （GroupMeal.EntityFrameworkCore）的 GroupMealDbContext 也默认使用 Default 连接字符串

                                                （通过 [ConnectionStringName("Default")] 标识）；

                                        <3>、即使模块有自己的 DbContext（如 Identity 模块的 IdentityDbContext），
                                            
                                                只要没有单独配置连接字符串，就会复用 Default 连接字符串，最终所有表（模块表 + 你的业务表）都会创建在 Default 对应的数据库中

                              简单说： 默认情况下，所有模块和你的业务代码共用一个数据库，无需手动配置。


                    2、验证：  如何确认模块表和业务表在同一个库？》

                                你可以通过以下步骤快速验证（以 SQL Server 为例）：

                                <1>、确保 appsettings.json 中只配置了 Default 连接字符串（无其他模块专属连接字符串）：

                                            {
                                                "ConnectionStrings": {
                                                    "Default": "Server=localhost;Database=GroupMealDb;Trusted_Connection=True;TrustServerCertificate=True;"
                                                }
                                            }

                                <2>、执行数据库迁移命令（生成迁移文件并应用到数据库）

                                            # 添加迁移（在 GroupMeal.EntityFrameworkCore 项目目录下执行）
                                            dotnet ef migrations add InitialCreate --project GroupMeal.EntityFrameworkCore --startup-project GroupMeal.Web

                                            # 应用迁移（创建数据库和表）
                                            dotnet ef database update --project GroupMeal.EntityFrameworkCore --startup-project GroupMeal.Web

                                <3>、打开 SQL Server Management Studio（SSMS），连接 GroupMealDb 数据库，会看到两类表：

                                            ★、模块表：以 Abp 为前缀（如 AbpUsers、AbpRoles、AbpTenants、AbpPermissionGrants 等）；

                                            ★、你的业务表：以 GroupMeal 为前缀（如 GroupMealGroups、GroupMealMeals 等，对应你声明的 DbSet）。



                    3、特殊情况：  模块表会 "不在同一个库" 吗？

                                只有以下两种情况，模块表才会创建在其他数据库中  (你不主动配置就不会触发)：

                                <1>、给模块单独配置了专属链接字符串

                                        比如在 appsettings.json 中给 Identity 模块配置了单独的连接字符串，那么 Identity 模块的表会创建在这个专属数据库中：

                                            {
                                                "ConnectionStrings": {
                                                    "Default": "Server=localhost;Database=GroupMealDb;...", // 你的业务表+其他模块表
                                                    "Identity": "Server=localhost;Database=GroupMeal_IdentityDb;..." // Identity 模块表单独存储
                                                }
                                            }

                                <2>、手动修改了模块的的连接字符串名称：


                                            比如通过代码给模块指定了非  Default 的连接字符串名称  (极少用)：

                                            // 不推荐：给 Identity 模块单独指定连接字符串名称
                                            [DependsOn(typeof(AbpIdentityEntityFrameworkCoreModule))]
                                            public class GroupMealIdentityModule : AbpModule
                                            {
                                                public override void ConfigureServices(ServiceConfigurationContext context)
                                                {
                                                    // 强制 Identity 模块使用 "Identity" 连接字符串
                                                    Configure<AbpDbContextOptions>(options =>
                                                    {
                                                        options.UseSqlServer().UseConnectionStringName("Identity");
                                                    });
                                                }
                                            }


                    4、关键总结：

                                <1>、默认行为：

                                            不做任何额外设置  (不替换模块的DbContext、不新增模块专属链接字符串)，内置模块的表会和你的业务表共用一个数据库。

                                <2>、无需担心模块表分散在多个数据库：

                                            只有你主动给模块配置的专属连接字符串，才会导致表分散。

                                <3>、无需替换DbContext:

                                            单库部署的需求，默认即可满足，无需通过 [ReplaceDbContext] 替换模块的 DbContext。
                                            (替换的目的是跨模块联表，而不是单库部署)


                    5、补充：  如何让模块表与业务表分开？

                                如果未来有「模块表独立存储」的需求（如租户数据单独分库），只需给模块配置专属连接字符串即可，无需修改 DbContext 代码 —— 这也体现了「不替换 DbContext」的灵活性。

    */

    /*
        三、两种模式的主要差别

                    先通过表格直观对比「替换 DbContext」和「不替换 DbContext」的核心区别，再对应到你的项目需求：


                        对比维度                         不替换DbContext                                     替换DbContext

                     1、数据库部署                  支持单库部署(默认)，或 多库部署(模块单独库)               强制单库  (被替换的模块实体、业务实体在同一个DbContext中，也必然在同一个库中)

                     2、跨模块联表查询              不支持直接联表 (需通过多上下文关联，复杂且低效)            支持直接联表 (所有实体在同一个 DbContext，EF Core 可直接解析） 

                     3、代码复杂度                 低                                                    高

                     4、模块独立性                 高                                                    低

                     5、扩展灵活性                 支持非侵入式扩展(阴影属性、继承实体)，不影响模块核心      扩展更灵活（可直接修改模块实体的映射配置），但侵入性强
                                                  逻辑

                     6、适用场景                  绝大多数项目：                                          复杂项目：
                                                    单库部署、无复杂跨模块联表、追求开发效率和兼容性            需频繁跨模块联表查询（如「租户 - 用户 - 订单」三联表）、需统一修改模块实体映射
    */
</script>